home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / PROGRAMMING / DESKLIBC / SOURCES.ZIP / DeskLib / !DLSources / Libraries / Menu2 / c / Menu2 < prev    next >
Text File  |  1995-07-22  |  7KB  |  318 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for 
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #                                      
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    Menu2.Menu2.c
  12.     Author:  Copyright © 1995 Julian Smith
  13.     Version: 1.00 (21 Jun 1995)
  14.     Purpose: Easy menu handling
  15. */
  16.  
  17.  
  18. #include <stdlib.h>
  19.  
  20. #include "DeskLib:Icon.h"
  21. #include "DeskLib:WimpSWIs.h"
  22. #include "DeskLib:Event.h"
  23. #include "DeskLib:Menu.h"
  24. #include "DeskLib:Error.h"
  25. #include "DeskLib:Debug.h"
  26. #include "DeskLib:Menu2.h"
  27.  
  28.  
  29.  
  30. typedef struct    {
  31.     char        *title;
  32.     char        *spec;
  33.     menu2_makefn    makefn;
  34.     menu2_flagsfn    flagsfn;
  35.     menu2_subfn    subfn;
  36.     menu2_selectfn    selectfn;
  37.     menu_ptr    menu;
  38.     void        *reference;
  39.     }
  40.     menu2_block;
  41.  
  42.  
  43.  
  44. #define menu2_MAXNEST    10
  45. static menu2_block    *menu2__openmenus[ menu2_MAXNEST+1];
  46. static int        menu2__numopen = 0;
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54. static void    Menu2__ClaimRelease( event_claimorreleasefn fn, void *reference);
  55.  
  56. #define Menu2__Claim( reference)            \
  57.     Menu2__ClaimRelease( Event_Claim, reference)
  58.  
  59. #define Menu2__Release( reference)            \
  60.     Menu2__ClaimRelease( Event_Release, reference)
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69. static void    Menu2__FreeMenu( menu2_block *m)
  70. /* Frees all data associated with menu2_block m    */
  71. /* Doesn't free submenus...            */
  72. {
  73. menu_item    *item = Menu_FirstItem( m->menu);
  74. for( ; ; item++)    {
  75.     Icon_DisposeIndData( &item->icondata, item->iconflags);
  76.     if ( item->menuflags.data.last)    break;
  77.     }
  78. free( m->menu);
  79. m->menu = NULL;
  80. }
  81.  
  82.  
  83. static void    Menu2__Free( int i)
  84. /* Free menus starting from nesting i    */
  85. {
  86. int    ii;
  87. Debug_Printf( "Menu2__Free, i=%i, menu2__numopen=%i\n", i, menu2__numopen);
  88.  
  89. for ( ii=i; ii<menu2__numopen; ii++)    {
  90.     
  91.     Debug_Printf( error_PLACE "menu2__openmenus[ ii(=%i)]->makefn = %p\n", 
  92.         ii, menu2__openmenus[ ii]->makefn
  93.         );
  94.     
  95.     if ( !menu2__openmenus[ ii]->makefn)    {
  96.         Debug_Printf( error_PLACE "Freeing menu number %i\n", ii);
  97.         Menu2__FreeMenu( menu2__openmenus[ ii]);
  98.         }
  99.     else    {
  100.         Debug_Printf( "Haven't free-d menu - it had a special creator function\n");
  101.         }
  102.     /* We don't free menus we haven't created    */
  103.     }
  104.  
  105. menu2__numopen = i;
  106. }
  107.  
  108.  
  109. menu2_handle    Menu2_Create( 
  110.     char            *title,
  111.     char            *spec,
  112.     menu2_makefn        makefn,        /* If !=NULL, called to make the menu    */
  113.     menu2_flagsfn        initfn,     /* Called every time menu is opened    */
  114.     menu2_subfn        subfn,        /* Called when submenu is needed    */
  115.     menu2_selectfn    selectfn,         /* Called when selection is made    */
  116.     void            *reference
  117.     )
  118. {
  119. menu2_block    *m = (menu2_block *) malloc( sizeof( menu2_block));
  120. if (!m)    return 0;
  121.     
  122. m->title    = title;
  123. m->spec        = spec;
  124. m->makefn    = makefn;
  125. m->flagsfn    = initfn;
  126. m->subfn    = subfn;
  127. m->selectfn    = selectfn;
  128. m->reference    = reference;
  129. m->menu        = NULL;
  130.  
  131. Debug_Printf( "Menu2_Create, title=%s, subfn=%p\n", title, subfn);
  132.  
  133. return (menu2_handle) m;
  134. }
  135.  
  136.  
  137.  
  138.  
  139.  
  140. static void    Menu2__EnsureMenu( menu2_block *m)
  141. {
  142. if ( m->menu == NULL)    {
  143.     if ( m->makefn)    {
  144.         Debug_Printf( "Menu2__EnsureMenu calling makefn at %p\n", m->makefn);
  145.         m->menu = m->makefn( m->reference);
  146.         }
  147.     else    {
  148.         m->menu = Menu_New( m->title, m->spec);
  149.         };
  150.     }
  151.  
  152. if ( m->flagsfn)    {
  153.     Debug_Printf( "Menu2__EnsureMenu calling flagsfn at %p\n", m->flagsfn);
  154.     m->flagsfn( m->menu, m->reference);
  155.     }
  156. }
  157.  
  158.  
  159.  
  160.  
  161. void    Menu2_Open( menu2_handle handle, int x, int y)
  162. {
  163. menu2_block    *m = (menu2_block *) handle;
  164.  
  165. Debug_Printf( "Menu2_Open called\n");
  166.  
  167. Menu2__Free( 0);    /* Close all menus    */
  168. Menu2__EnsureMenu( m);
  169. Menu_Show( m->menu, x, y);
  170. menu2__openmenus[0] = m;
  171. menu2__numopen = 1;
  172. Menu2__Claim( NULL);
  173. }
  174.  
  175.  
  176.  
  177.  
  178. static int    Menu2__SelectionDepth( int *selections)
  179. /* Returns the number of menus in the selection    */
  180. {
  181. int    i;
  182. for ( i=0; selections[i]!=-1; i++)    ;
  183. Debug_Printf( "Menu2__SelectionDepth, returning %i\n", i);
  184. return i;
  185. }
  186.  
  187.  
  188.  
  189.  
  190. static void    Menu2__OpenSub( event_pollblock *event, menu2_handle handle)
  191. {
  192. menu2_block    *m = (menu2_block *) handle;
  193. int        selectdepth = Menu2__SelectionDepth( &event->data.message.data.words[3]);
  194.  
  195. Debug_Printf( "Menu2__OpenSub, handle=%i, selectdepth= %i\n", handle, selectdepth);
  196.  
  197. Menu2__Free( selectdepth);
  198.     
  199. Menu2__EnsureMenu( m);
  200. Wimp_CreateSubMenu(
  201.     m->menu,
  202.     event->data.message.data.words[1], 
  203.     event->data.message.data.words[2]
  204.     );
  205.  
  206. menu2__openmenus[ menu2__numopen] = m;
  207. menu2__numopen++;
  208. }
  209.  
  210.  
  211.  
  212.  
  213.  
  214. static BOOL    Menu2__MessageHandler( event_pollblock *event, void *reference)
  215. {
  216. UNUSED( reference);
  217.  
  218. Debug_Printf( "Menu2__MessageHandler\n");
  219.  
  220. if ( event->data.message.header.action == message_MENUWARN)    {
  221.  
  222.     int        *selections    = &event->data.message.data.words[3];
  223.     int        selectdepth    = Menu2__SelectionDepth( selections);
  224.     menu2_block    *lastmenu    = menu2__openmenus[ selectdepth-1];
  225.     menu2_handle    nextmenu = NULL;
  226.     
  227.     Menu2__Free( selectdepth);
  228.     Debug_Printf( "Menu2__MessageHandler, menu2__numopen=%i\n", menu2__numopen);
  229.     
  230.     if ( menu2__numopen < selectdepth)    return FALSE;
  231.         /* Some menus are open which we don't know about...    */
  232.     
  233.     if ( lastmenu->subfn)    {
  234.         Debug_Printf( "Menu2__MessageHandler, calling subfn %p\n", lastmenu->subfn);
  235.         nextmenu = lastmenu->subfn( 
  236.             selections[ selectdepth-1], 
  237.             event, 
  238.             lastmenu->reference
  239.             );
  240.         Debug_Printf( "Menu2__MessageHandler, nextmenu=%i\n", nextmenu);
  241.         if (nextmenu)    Menu2__OpenSub( event, nextmenu);
  242.         }
  243.     }
  244.  
  245. else if ( event->data.message.header.action == message_MENUSDELETED)    {
  246.     Menu2__Free( 0);
  247.     Menu2__Release( reference);
  248.     }
  249.  
  250. return FALSE;
  251. }
  252.  
  253.  
  254. static BOOL    Menu2__MenuHandler( event_pollblock *event, void *reference)
  255. {
  256. /*int        selectdepth    = Menu2__SelectionDepth( &event->data.selection[0]);*/
  257. menu2_block    *leafmenu    = menu2__openmenus[ menu2__numopen-1];
  258. mouse_block    mouse;
  259.  
  260. Wimp_GetPointerInfo( &mouse);
  261.  
  262. if ( leafmenu->selectfn)    {
  263.     Debug_Printf( "Menu2__MenuHandler calling selectfn %p\n", leafmenu->selectfn);
  264.     leafmenu->selectfn( event->data.selection[ menu2__numopen-1], leafmenu->reference);
  265.     }
  266.     /*
  267.     Note that this is not necessarily the leaf menu, just the
  268.     leaf-est menu2 opened. This is because the last menu2 
  269.     could have opened non-menu2 menus itself.
  270.     */
  271.  
  272. if ( !mouse.button.data.adjust)    Wimp_GetPointerInfo( &mouse);
  273.     /* Have a second chance to use Adjust (eg if selecfn    */
  274.     /* brought up an error-box.                */
  275.  
  276. if ( mouse.button.data.adjust)    {
  277.  
  278.     int    i;
  279.     
  280.     /* Rescan all open menus...    */
  281.     Debug_Printf( "Menu2__MenuHandler reopening menu\n");
  282.     
  283.     for ( i=0; i<menu2__numopen; i++)    {
  284.         menu2_block    *m = menu2__openmenus[ i];
  285.         if ( m->flagsfn)    {
  286.             Debug_Printf( "Menu2__MenuHandler calling flagsfn\n");
  287.             /*Debug_Printf( "menublock is %p %p %p %p %p %p %p %p\n",
  288.                 m->title, m->spec, m->makefn, m->flagsfn, m->subfn,
  289.                 m->selectfn, m->menu, m->reference
  290.                 );
  291.             */
  292.             m->flagsfn( m->menu, m->reference);
  293.             }
  294.         }
  295.         
  296.     Debug_Printf( "Menu2__MenuHandler calling Menu_ShowLast\n");    
  297.     Menu_ShowLast();
  298.     }
  299.  
  300. else    {
  301.     Menu2__Free( 0);
  302.     Menu2__Release( reference);
  303.     }
  304.  
  305. return FALSE;
  306. }
  307.  
  308.  
  309.  
  310.  
  311. static void    Menu2__ClaimRelease( event_claimorreleasefn fn, void *reference)
  312. {
  313. fn( event_USERMESSAGE, event_ANY, event_ANY, Menu2__MessageHandler, reference);
  314. fn( event_USERMESSAGERECORDED, event_ANY, event_ANY, Menu2__MessageHandler, reference);
  315. fn( event_MENU, event_ANY, event_ANY, Menu2__MenuHandler, reference);
  316. }
  317.  
  318.